package com.slb.slnwp.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

/**
 * @author: joinly
 * @date: 2023/11/10 15:31
 * @desc: jwt工具类
 **/
@Slf4j
public class JwtTokenUtil {

    //token过期时长30分钟
    private static final long EXPIRE_TIME = 10 * 60 * 1000;

    //token私钥
    private static final String SECRET = "joinly";

    private static final String USERNAME = "username";
    /**
     * 生成token
     * 用于生成 JSON Web Token (JWT) 的方法，用于进行用户身份验证
     *
     * @param userId
     * @param username
     * @return
     */
    public static String sign(String userId, String username) {
        // 动态秘钥，将用户名和预定义的密钥（SECRET）拼接作为秘钥
        String TOKEN_SECRET = username + SECRET;
        // 创建一个日期对象，表示 Token 的过期时间
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        log.info("System.currentTimeMillis() == {}", System.currentTimeMillis());
        log.info("System.currentTimeMillis() + EXPIRE_TIME == {}", System.currentTimeMillis() + EXPIRE_TIME);
        // 使用 HMAC256 签名算法，使用 TOKEN_SECRET 作为秘钥
        Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        // 创建 JWT，并设置相关的声明（claims）
        return JWT.create()
                .withClaim(USERNAME, username)
                .withClaim("userId", userId)
                .withExpiresAt(date)
                .sign(algorithm);
    }

    /**
     * 动态秘钥验证 JSON Web Token (JWT) 的 方法
     * @param token
     * @return
     * @Description token解码校验
     * @Create 2020-03-03 by jjy
     */
    public static boolean verfiy(String token) {
        try {
            // 动态秘钥 使用 HMAC256 算法 创建
            String TOKEN_SECRET = getClaim(token, USERNAME) + SECRET;
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            // 验证 JWT
            JWTVerifier jwtVerifier = JWT.require(algorithm).build();
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            // 检查 DecodedJWT 中的过期时间是否在当前时间之前，如果是，则说明该 JWT 已过期
            if (System.currentTimeMillis() > decodedJWT.getExpiresAt().getTime()) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 获得token中的信息，无需secret解密也能获得
     * 用于从 JWT 中获取声明（claim）值
     *
     * @param token 令牌
     * @param claim 需要获取的信息
     * @return token中包含的用户名
     */
    public static String getClaim(String token, String claim) {

        try {
            // 解码 JWT
            DecodedJWT jwt = JWT.decode(token);
            // 获取并返回 声明值
            return jwt.getClaim(claim).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

}
